Technical Q&A

OPS 19 - 実行可能なデータの作成(1999 年 4 月 12 日)


Q: 現在、オンザフライにマシンコードを構築するプログラムを書いています。新しく構築した命令を実行できるように、プロセッサキャッシュを正しくフラッシュする方法を教えてください。

A: この質問に対する回答は、構築しているコードの命令セットアーキテクチャ (ISA) によって変わります。

  • 68K コードを構築している場合は、FlushCodeCacheRange を呼び出す必要があり、これがエラーを返す場合は、FlushCodeCache を呼び出します。
  • PowerPC コードを構築している場合は、MakeDataExecutable を呼び出す必要があります。

重要:
回答が実行しているコードの ISA に依存することはありません。たとえば、68K コードを構築する PowerPC コードを書いている場合は、MakeDataExecutable ではなく FlushCodeCacheRange を呼び出す必要があります。同様に、PowerPC コードを構築する 68K コードを書いている場合は、MakeDataExecutable を呼び出す必要があります。

警告:
FlushInstructionCache または FlushDataCache のいずれかを使って、実行可能な 68K データを作成することはできません。実行可能な 68K データを正しく作成するには、両方のキャッシュを正しい順序でフラッシュする必要があります。FlushCodeCacheRange と FlushCodeCache がこの処理を行ってくれます。これら 2 つの関数の使用を推奨している理由はここにあります。

Macintosh のキャッシュアーキテクチャがどのようにソフトウェアに影響を与えるかについては、 HW 06 Cache as Cache Can を参照してください。

DTS サンプルコードライブラリ「MoreIsBetter」には、68K または PowerPC コードとして実行可能なデータを作成する方法を具体的に示したモジュール (「MoreOSUtils」) が含まれています。このモジュールは、以下に示す複雑な状況をすべて処理します。

このルーチンを呼び出すときに考慮すべき重要な問題がいくつかあります。

  • FlushCodeCacheRange は、Mac OS 8.1 以前では InterfaceLib によってエクスポートされません。Mac OS 8.5 より前の CFM コードから FlushCodeCacheRange を使用したい場合は、独自の Mixed Mode グルーを書く必要があります。このための一般的なテクニックについては、「Technote 1127 「失われた」リンクを求めて」を参照してください。
  • FlushCodeCacheRange は、Mac OS 8.5 以降では InterfaceLib によってエクスポートされます。これにアクセスするには、Universal Interfaces 3.2 またはそれ以上の InterfaceLib スタブライブラリをリンクする必要があります。
  • Universal Interfaces のバージョンによっては、次に示す 1 つまたは 2 つのバグがあります。
    1. FlushCodeCacheRange の不正なプロトタイプ -- Universal Interfaces の 古いバージョンでは、FlushCodeCacheRange の結果が OSErr ではなく void になるように定義されています。正しいキャッシュフラッシュアルゴリズムでは FlushCodeCacheRange の実行結果をテストすることを要求するため、この定義には問題があります。
    2. 不正な条件 -- Universal Interfaces の古いバージョンでは、CFM コードで使用できないように、FlushCodeCacheRange を条件つきで定義しています。しかし、すでに説明したように、68K コードを生成する場合には FlushCodeCacheRange を呼び出すことが重要であり、PowerPC コードを使って 68K 命令を生成する場合にも FlushCodeCacheRange が必要です。

    次に、Universal Interfaces のバージョン別にどのような問題を抱えているかを示します。

    Universal Interfaces Version

    不正なプロトタイプ

    不正な条件

    2.1.4 以前

    Yes

    Yes

    3.0, 3.0.1, 3.1

    No

    Yes

    3.2

    No

    No

  • PowerPC ベースのコンピュータは常に FlushCodeCacheRange をインプリメントします。このため、PowerPC コードを実行する場合に FlushCodeCache を呼び出す必要はありません。
  • 一部の古い 68K ベースのコンピュータは _HWPriv (FlushCodeCacheRange の基盤となるトラップ) をインプリメントしていないことがあります。開発中のアプリケーションが 68K ベースのコンピュータで実行される可能性がある場合は、FlushCodeCacheRange を呼び出す前に、_HWPriv トラップが使用可能であるかどうかをテストしてください。
  • MakeDataExecutable はトラップを持ちません。PowerPC ベースのコンピュータでクラシック 68K コードを実行している場合は、CFM と Mixed Mode を明示的に呼び出して、このルーチンを実行する必要があります。このための一般的なテクニックについては、「Technote 1077 Calling CFM Code From Classic 68K Code」を参照してください。
  • 特に、サイズの大きな 68K コードのチャンクを移動しているときに、最も簡単に 68K 命令キャッシュをフラッシュする方法はおそらく BlockMove です。『Inside Macintosh: Memory』には、12 バイトまたはそれ以上のブロックを移動するときに、BlockMove が適切なフラッシュを行うことが説明されています。

Macintosh の命令キャッシュの詳細については、次のテクニカルノートを参照してください。


この Q&A を校閲してくれた Craig Prouse (DTS 名誉スタッフ) に感謝します。



-- Quinn "The Eskimo!"
Worldwide Developer Technical Support

Technical Q&As | Contents
Previous Question | Next Question

To contact us, please use the Contact Us page.